package basic.sort.greedy;


import java.util.Arrays;
import java.util.Comparator;

/**
 * @author distantstar
 * @version 1.0
 * @date 2021
 * @description basic.sort.greedy
 * @since JDK1.8
 */
public class BestArrange {

    /**
     * 会议类
     */
    private static class Program {
        public int start;
        public int end;

        public Program(int start, int end) {
            this.start = start;
            this.end = end;
        }
    }

    // 暴力
    private static int violence(Program[] programs) {
        if (programs == null || programs.length == 0) {
            return 0;
        }
        return process(programs, 0, 0);
    }

    /**
     * 用全排列的方式求最多可安排次数
     * @param programs 会议列表
     * @param done 已经安排的会议次数
     * @param time 当前结束时间
     * @return 返回最大可安排会议次数
     */
    private static int process(Program[] programs, int done, int time) {
        if (programs.length == 0) {
            return done;
        }

        // 最多安排会议次数
        int max = done;
        // 循环找出最多次数
        for (int i = 0; i < programs.length - 1; ++i) {
            // 判断当前开始时间是否大于结束时间
            if (programs[i].start >= time) {
                // 纯暴力复制所有的会议（不包含当前会议），然后继续求解
                Program[] next = copyButExcept(programs, i);
                max = Math.max(max, process(next, done + 1, programs[i].end));
            }
        }

        return max;
    }

    private static Program[] copyButExcept(Program[] programs, int i) {
        Program[] ans = new Program[programs.length - 1];
        int index = 0;
        for (int k = 0; k < programs.length; k++) {
            if (k != i) {
                ans[index++] = programs[k];
            }
        }
        return ans;
    }

    public static int greedy(Program[] programs) {
        // 根据结束时间早晚决定
        Arrays.sort(programs, new ProgramComparator());
        // 结束时间
        int timeLine = 0;
        // 可安排次数
        int result = 0;
        // 依次遍历每一个会议，结束时间早的会议先遍历
        for (Program program : programs) {
            if (timeLine <= program.start) {
                result++;
                timeLine = program.end;
            }
        }
        return result;
    }

    public static class ProgramComparator implements Comparator<Program> {

        @Override
        public int compare(Program o1, Program o2) {
            return o1.end - o2.end;
        }

    }

    public static Program[] generatePrograms(int programSize, int timeMax) {
        Program[] ans = new Program[(int) (Math.random() * (programSize + 1))];
        for (int i = 0; i < ans.length; i++) {
            int r1 = (int) (Math.random() * (timeMax + 1));
            int r2 = (int) (Math.random() * (timeMax + 1));
            if (r1 == r2) {
                ans[i] = new Program(r1, r1 + 1);
            } else {
                ans[i] = new Program(Math.min(r1, r2), Math.max(r1, r2));
            }
        }
        return ans;
    }

    public static void main(String[] args) {
        int programSize = 12;
        int timeMax = 20;
        int timeTimes = 1000000;
        for (int i = 0; i < timeTimes; i++) {
            Program[] programs = generatePrograms(programSize, timeMax);
            if (violence(programs) != greedy(programs)) {
                System.out.println("Oops!");
            }
        }
        System.out.println("finish!");
    }
}
